/*
 * Copyright (c) 2012 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.libermundi.theorcs.core.tapestry.mixins;

import org.apache.tapestry5.Asset;
import org.apache.tapestry5.BindingConstants;
import org.apache.tapestry5.CSSClassConstants;
import org.apache.tapestry5.ComponentEventCallback;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.Field;
import org.apache.tapestry5.Link;
import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.annotations.AfterRender;
import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.InjectContainer;
import org.apache.tapestry5.annotations.OnEvent;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.Path;
import org.apache.tapestry5.annotations.RequestParameter;
import org.apache.tapestry5.annotations.SetupRender;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
import org.got5.tapestry5.jquery.ImportJQueryUI;
import org.libermundi.theorcs.core.tapestry.model.RealTimeValidationResponse;

/**
 * @author Martin Papy
 *
 */
@ImportJQueryUI("jquery.ui.widget")
@Import(library={
	"${core.scripts}/jquery.realtimevalidation.js",
	"${core.scripts}/t5.realtimevalidation.js"
})
public class RealTimeValidation {
	private static final String INTERNAL_EVENT_NAME = "realtimevalidation";

	public static final String EVENT_NAME = "providevalidation";
	
    private static final String PARAM_NAME = "t:input";
    
    /**
     * The field component to which this mixin is attached.
     */
    @InjectContainer
    private Field _field;
    
    @Inject
    private ComponentResources _resources;

    @Environmental
    private JavaScriptSupport _jsSupport;

    @Inject
    @Path("${tapestry.spacer-image}")
    private Asset _spacerImage;
    
    /**
     * Overwrites the default minimum characters to trigger a server round trip (the default is 1).
     */
    @Parameter(defaultPrefix = BindingConstants.LITERAL)
    private int _minChars;
    
    @Parameter(defaultPrefix = BindingConstants.LITERAL, value="realTimeValidationCallBack", required=false)
    private String _onValidateCallBack;

    @Inject
    @Path("${core.scripts}/callback.realtimevalidation.js")
	private Asset _defaultCallBackLibrary;
    
    @SetupRender
    public void setupRender(){
    	if(_onValidateCallBack.equals("realTimeValidationCallBack")){
    		_jsSupport.importJavaScriptLibrary(_defaultCallBackLibrary);
    	}
    }
    
    /**
     * Mixin afterRender phrase occurs after the component itself. This is where we write the &lt;div&gt; element and
     * the JavaScript.
     * 
     * @param writer
     */
    @AfterRender
    void afterRender(MarkupWriter writer) {
        String id = _field.getClientId();

        String loaderId = id + "_loader";

        // The spacer image is used as a placeholder, allowing CSS to determine what image
        // is actually displayed.

        writer.element("img",
	        "src", _spacerImage.toClientURL(),
	
	        "class", "t-autoloader-icon " + CSSClassConstants.INVISIBLE,
	
	        "alt", "",
	
	        "id", loaderId
	    );
	    writer.end();
	
        Link link = _resources.createEventLink(INTERNAL_EVENT_NAME);

        JSONObject config = new JSONObject();
        config.put("paramName", PARAM_NAME);
        config.put("indicator", loaderId);
        config.put("url", link.toURI());

        if (_resources.isBound("minChars")){
        	config.put("minChars", _minChars);
        }
        
        if (_resources.isBound("onValidateCallBack")) {
        	config.put("onValidateCallBack",_onValidateCallBack);
        }

        JSONObject spec = new JSONObject("elementId", id).put("config", config);

        _jsSupport.addInitializerCall("realtimevalidation", spec);
    }
    
    @OnEvent(INTERNAL_EVENT_NAME)
    public JSONObject onRealTimeValidation(@RequestParameter(PARAM_NAME) String input) {
    	final JSONObject response = new JSONObject();


        ComponentEventCallback<RealTimeValidationResponse> callback = new ComponentEventCallback<RealTimeValidationResponse>() {
            @Override
			public boolean handleResult(RealTimeValidationResponse result) {
            	response.put("success", result.getValidationResult().toString());
            	response.put("message", result.getValidationMessage());

                return true;
            }
        };

        _resources.triggerEvent(RealTimeValidation.EVENT_NAME, new Object[]{ input }, callback);
        

        return response;
    }
    
    
}
